import serial
import struct
from collections import deque

# 串口配置（根据实际设备修改）
SERIAL_PORT = '/dev/ttyS3'  # 串口号
BAUD_RATE = 9600      # 波特率

# 协议常量
START_BYTES = b'\xFE\x01'  # 起始位
END_BYTES = b'\xEF\x10'    # 结束位
CMD_CALIBRATE = 0x01       # 指令位

# 缓存机制
PACKET_BUFFER_SIZE = 11  # 最大数据包长度（包括起始位、指令位、数据、校验和、结束位）
PACKET_BUFF = deque(maxlen=PACKET_BUFFER_SIZE)

def calculate_checksum(command, data):
    """计算校验和：指令位 + 所有数据字节之和,保留低2字节"""
    total = command
    for byte in data:
        total += byte
    return total & 0xFFFF  # 取低16位

def parse_packet(packet):
    """
    解析接收到的数据包。

    :param packet: 接收到的原始字节数据包
    :return: 如果解析成功，返回包含指令、横坐标和纵坐标的字典；否则返回 None
    """
    # 检查起始位和结束位
    if packet[:2] != START_BYTES or packet[-2:] != END_BYTES:
        print("错误：帧头帧尾不匹配")
        return None
    
    # 解析数据部分（总长度为 2+1+4+2+2=11字节）
    # 结构：起始位(2) + 指令(1) + 横坐标(2) + 纵坐标(2) + 校验和(2) + 结束位(2)
    try:
        # 使用struct解包（大端模式）
        command = packet[2]
        x_coord = struct.unpack('>H', packet[3:5])[0]
        y_coord = struct.unpack('>H', packet[5:7])[0]
        received_checksum = struct.unpack('>H', packet[7:9])[0]
        
        # 计算校验和
        calculated_checksum = calculate_checksum(command, packet[3:7])
        
        if received_checksum != calculated_checksum:
            print(f"错误：校验和不匹配（收到：{received_checksum:04X}，计算：{calculated_checksum:04X}）")
            return None
        
        return {
            'command': command,
            'x': x_coord,
            'y': y_coord
        }
    
    except Exception as e:
        print(f"解析错误：{str(e)}")
        return None

def create_response(command, status):
    """生成应答数据包"""
    # 校验和计算：指令位 + 状态字节
    checksum = calculate_checksum(command, [status])
    
    # 组装数据包
    response = (
        START_BYTES +                # 起始位
        struct.pack('B', command) +  # 指令位
        struct.pack('B', status) +   # 状态位
        struct.pack('>H', checksum) + # 校验和
        END_BYTES                    # 结束位
    )
    return response

def main():
    # 初始化串口
    ser = serial.Serial(SERIAL_PORT, BAUD_RATE)
    print(f"监听串口 {SERIAL_PORT}，波特率 {BAUD_RATE}...")

    try:
        while True:
            # print("等待接收数据...")
            packet = ser.read(1)
            if not packet:
                continue
            print(f"收到一个字节：{packet.hex(' ')}")
            PACKET_BUFF.append(packet)

            # 检查是否有完整的数据包
            if len(PACKET_BUFF) < 11:
                continue  # 数据包不完整，继续等待
            # 检查起始位和结束位
            packet_bytes = b''.join(PACKET_BUFF)
            if packet_bytes[:2] != START_BYTES or packet_bytes[-2:] != END_BYTES:
                # print("错误：帧头帧尾不匹配")
                # print(f'当前缓存：{[byte.hex(" ") for byte in PACKET_BUFF]}')
                PACKET_BUFF.popleft()  
                continue
            print(f"完整数据包：{packet_bytes.hex(' ')}")
            
            # 解析数据包
            data = parse_packet(packet_bytes)
            if data:
                print(f"解析成功：指令={data['command']:02X}，坐标=({data['x']}, {data['y']})")
                
                # 生成应答（这里简单返回正常应答，实际可加业务逻辑）
                response = create_response(data['command'], 0x00)
                ser.write(response)
                print(f"发送应答：{response.hex(' ')}")

    except KeyboardInterrupt:
        print("程序终止")
    finally:
        ser.close()

if __name__ == '__main__':
    main()